package org.zero.concurrency.demo.example.sync;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @program: concurrency-demo
 * @description: Synchronized demo
 * @author: 01
 * @create: 2018-10-16 13:02
 **/
@Slf4j
public class SynchronizedExample1 {

    /**
     * 修饰一个代码块
     */
    public void test1() {
        synchronized (this) {
            for (int i = 0; i < 10; i++) {
                log.info("test1 - {}", i);
            }
        }
    }

    /**
     * 修饰一个方法
     * 若子类继承父类调用父类的synchronized方法，是带不上synchronized关键字的
     * 原因：synchronized 不属于方法声明的一部分
     * 如果子类也想使用同步需要在方法上声明
     */
    public synchronized void test2() {
        for (int i = 0; i < 10; i++) {
            log.info("test2 - {}", i);
        }
    }

    public static void main(String[] args) {
        SynchronizedExample1 example1 = new SynchronizedExample1();
        SynchronizedExample1 example2 = new SynchronizedExample1();

        // 使用线程池模拟多线程同时调用同一段sync代码
        ExecutorService executorService = Executors.newCachedThreadPool();

        // 由于同步块的作用，所以线程pool-1-thread-1 先输出0-9，然后pool-1-thread-2 再输出0-9
        executorService.execute(example1::test1);
        executorService.execute(example1::test1);

        // 由于同步方法只作用于调用该方法的对象，而这里分别使用了不同对象进行调用
        // 所以这里线程 pool-1-thread-1和pool-1-thread-2 是交叉输出的
        executorService.execute(example1::test2);
        executorService.execute(example2::test2);

        executorService.shutdown();
    }
}
